/*
 * 代号：凤凰
 * http://www.jphenix.org
 * 2022年11月29日
 * V4.0
 */
package com.jphenix.driver.udp;

import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;

import com.jphenix.standard.docs.ClassInfo;

/**
 * 消息状态信息VO
 * 
 * com.jphenix.driver.udp.MsgStateVO
 * 
 * 该类主要用于驻留内存保存与客户端连接的信息，以及往指定客户端发送消息。
 * 并不解析信息报文，解析报文需要用到MsgVO，在服务端收到请求后，需要先解析报文
 * 然后根据报文内容，将必要信息放入MsgStateVO中，将这个类驻留内存，用于回复客户端信息
 * 
 * @author mbg
 * 2022年11月29日
 */
@ClassInfo({"2022-11-29 14:45","消息状态信息VO"})
public class MsgStateVO {

	//#region 变量声明区
	public String          token              = null; // token
	public String          sysCode            = null; // 系统代码
	public DatagramChannel channel            = null; // 通信类
	public String          receiveServiceCode = null; // 接收到客户端发过来的服务代码
	public String          receiveData        = null; // 接收到客户端发过来的数据
	public long            receiveTs          = 0;    // 最后接收消息时间戳
	public char            sendType           = 'M';  // 服务端往客户端发送消息类型
	public String          sendCode           = null; // 服务器往客户端发送消息代码
	public String          sendData           = null; // 服务器往客户端发送消息数据
	public long            sendTs             = 0;    // 服务器往客户端最后发送消息时间戳
	public SocketAddress   sendAddress        = null; // 服务器往客户端发送消息，客户端地址对象
	public Exception       sendException      = null; // 发送时异常对象
	protected long         tokenTs            = System.currentTimeMillis(); // 会话时间
	//#endregion
	
	//#region 构造函数
	/**
	 * 构造函数
	 * @author mbg
	 */
	public MsgStateVO() {
		super();
	}
	//#endregion

	//#region receive(channel,vo) 设置客户端发送消息给服务端的数据
	/**
	 * 设置客户端发送消息给服务端的数据
	 * @param channel 通信类
	 * @param address 客户端
	 * @param vo      数据对象
	 * 2022年11月29日
	 * @author mbg
	 */
	public void receive(DatagramChannel channel,SocketAddress address,MsgVO vo) {
		this.channel            = channel;
		this.sendAddress        = address;
		this.token              = vo.token;
		this.sysCode            = vo.sysCode;
		this.receiveServiceCode = vo.serviceCode;
		this.receiveData        = vo.parameter;
		this.receiveTs          = System.currentTimeMillis();
		refreshTs();
	}
	//#endregion
	
	//#region sendMsg(code,data) 服务端发消息到客户端
	/**
	 * 服务端发消息到客户端
	 * @param code  代码
	 * @param data  数据
	 * @return      发送数据时间戳
	 * 2022年11月29日
	 * @author mbg
	 */
	public long sendMsg(String code,String data) {
		return doSend(code,data,false);
	}
	//#endregion
	
	//#region endError(code,msg) 执行推送错误信息
	/**
	 * 执行推送错误信息
	 * @param code  错误代码
	 * @param msg   错误信息
	 * @return      发送时间戳
	 * 2022年11月29日
	 * @author mbg
	 */
	public long sendError(String code,String msg) {
		return doSend(code,msg,true);
	}
	//#endregion
	
	//#region doSend(code,data,isError) 发送消息到客户端
	/**
	 * 发送消息到客户端
	 * @param code     消息代码
	 * @param data     数据
	 * @param isError  是否推送错误消息
	 * @return         发送数据的时间戳
	 * 2022年11月29日
	 * @author mbg
	 */
	private long doSend(String code,String data,boolean isError) {
		sendException    = null;
		ByteBuffer resBb = null; // 返回数据对象
		sendTs = System.currentTimeMillis();
		try {
			if(isError) {
				resBb = MsgVO.respError(sysCode,token,code,data);
			}else {
				resBb = MsgVO.response(sysCode,token,code,data);
			}
			if(resBb==null) {
				return sendTs;
			}
			resBb.flip();
			channel.send(resBb,sendAddress);
		}catch(Exception e) {
			sendException = e;
			e.printStackTrace();
		}
		return sendTs;
	}
	//#endregion

	//#region refreshTs() 刷新会话时间
	/**
	 * 刷新会话时间
	 * 2022年11月29日
	 * @author mbg
	 */
	public void refreshTs() {
		tokenTs = System.currentTimeMillis();
	}
	//#endregion
	
	//#region toString() 覆盖方法
	/**
	 * 覆盖方法
	 */
	public String toString() {
		// 构建返回值
		StringBuffer sbf = new StringBuffer();
		sbf.append("MsgStateVO:\n address:").append(sendAddress)
		.append("\n sysCode:[").append(sysCode).append("]\n token:[")
		.append(token).append("]\n receiveServiceCode:[").append(receiveServiceCode)
		.append("]\n receiveData:[").append(receiveData).append("]\n");
		return sbf.toString();
	}
	//#endregion
}




